package edu.cornell.lsi;

import java.io.IOException;
import java.io.PrintWriter;
import java.net.InetAddress;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;

import javax.servlet.RequestDispatcher;
import javax.servlet.ServletConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import edu.cornell.cs.lsi.projone.common.util.AppUtil;
import edu.cornell.cs.lsi.projone.model.SessionTableData;
import edu.cornell.cs.lsi.projone.service.SessionTableManager;

// Servlet for Replace action
public class ReplaceServlet extends HttpServlet {

	ServletConfig config;
	private long sessionTimeout = 0;
	private SessionTableManager sessionTableMgr;

	// Read the context parameters
	@Override
	public void init(ServletConfig config) throws ServletException {

		this.config = config;
		super.init(config);
		ServletContext context = getServletContext();
		sessionTimeout = Long.valueOf(context
				.getInitParameter("session_timeout_msec"));
		System.out.println(" ====================== session time out "
				+ sessionTimeout);
		sessionTableMgr = new SessionTableManager();
	}

	// Calls doPost for processing
	@Override
	protected void doGet(HttpServletRequest request,
			HttpServletResponse response) throws ServletException, IOException {
		doPost(request, response);
	}

	// POST method process request and send response
	@Override
	protected void doPost(HttpServletRequest request,
			HttpServletResponse response) throws ServletException, IOException {

		Cookie cookie = null;
		String sessionID = null;
		double cookieVersionID = 0;
		double versionID = 0;
		int counter = 1;
		String value = null;
		String timeStamp = null;
		SessionTableData sessionData = null;

		// Checks is session data value exceeds the size limit
		boolean sizeOverLimit = false;

		// Get the current time
		DateFormat dateFormat = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
		Date date = new Date();
		String currentTime = dateFormat.format(date);
		Cookie[] cookies = request.getCookies();

		// If cookie is null redirect to home page
		if (cookies == null) {

			// response.setStatus(HttpServletResponse.SC_MOVED_TEMPORARILY);
			// response.setHeader("Location", "http://localhost:8080/lsi/home");
			// response.setContentType("text/html");
			RequestDispatcher dispatch = request.getRequestDispatcher("/home");
			dispatch.forward(request, response);

			return;

			// Retrieve the cookie values if not null
		} else {

			cookie = cookies[0];
			String[] cookieValues = cookie.getValue().split(" ");
			sessionID = cookieValues[0];
			cookieVersionID = Double.parseDouble(cookieValues[1]);
			String newValue = request.getParameter("NewText");

			// Check if Session Data Table has the session ID
			if (sessionTableMgr.containsSession(sessionID)) {

				// Retrieve session data from table
				sessionData = sessionTableMgr.getEntry(sessionID,
						cookieVersionID);
				versionID = sessionData.getVersionNumber();
				value = sessionData.getSessionVal();
				counter = sessionData.getCounter();
				timeStamp = sessionData.getSessionCreationTime();

				// if session timed out redirect to logout page
				if (SessionTableManager.isTimedOut(timeStamp, currentTime,
						sessionTimeout)) {
					// response.setStatus(HttpServletResponse.SC_MOVED_TEMPORARILY);
					// response.setHeader("Location","http://localhost:8080/lsi/logout");
					// response.setContentType("text/html");

					RequestDispatcher dispatch = request
							.getRequestDispatcher("/logout");
					dispatch.forward(request, response);
					return;
				}

				// if version mismatch redirect to error page
				if (cookieVersionID != versionID) {
					// response.setStatus(HttpServletResponse.SC_MOVED_TEMPORARILY);
					// response.setHeader("Location","http://localhost:8080/lsi/error");
					// response.setContentType("text/html");
					RequestDispatcher dispatch = request
							.getRequestDispatcher("/error");
					dispatch.forward(request, response);
					return;
				}

				// Redirect to logout page if Session ID is timed out through
				// background process
			} else {

				sessionData = SessionTableManager.fetchSession(sessionID + " "
						+ cookieVersionID);

				if (sessionData == null) {
					// response.setStatus(HttpServletResponse.SC_MOVED_TEMPORARILY);
					// response.setHeader("Location",
					// "http://localhost:8080/lsi/logout");
					// response.setContentType("text/html");
					RequestDispatcher dispatch = request
							.getRequestDispatcher("/logout");
					dispatch.forward(request, response);
					return;
				} else {

					versionID = sessionData.getVersionNumber();
					value = sessionData.getSessionVal();
					counter = sessionData.getCounter() + 1;
					timeStamp = sessionData.getSessionCreationTime();

					// if session timed out redirect to logout page
					if (SessionTableManager.isTimedOut(timeStamp, currentTime,
							sessionTimeout)) {
						response.setStatus(HttpServletResponse.SC_MOVED_TEMPORARILY);
						// response.setHeader("Location",
						// "http://localhost:8080/lsi/logout");
						// response.setContentType("text/html");
						RequestDispatcher dispatch = request
								.getRequestDispatcher("/logout");
						dispatch.forward(request, response);
						return;
					}

					// if version mismatch redirect to error page
					if (cookieVersionID != versionID) {
						// response.setStatus(HttpServletResponse.SC_MOVED_TEMPORARILY);
						// response.setHeader("Location",
						// "http://localhost:8080/lsi/error");
						// response.setContentType("text/html");
						RequestDispatcher dispatch = request
								.getRequestDispatcher("/error");
						dispatch.forward(request, response);
						return;
					}

				}

			}

			// if newValue field is null then increment the counter because it
			// is a refresh from the browser tab
			if (newValue == null) {
				counter += 1;

				// if newValue is not null check the size. If within limit set
				// the value
			} else {

				byte[] bytes = newValue.getBytes();
				int size = bytes.length;

				if (size > 1024) {
					sizeOverLimit = true;
				}

			}

			if (!sizeOverLimit) {
				value = newValue;
				counter = 1;
			}
		}

		String errorString = " ";
		// increment the version
		versionID += 1;

		// update the user session data and cookie
		sessionData.update(versionID, currentTime, counter, value);
		sessionTableMgr.addEntry(sessionData);
		String serverList = SessionTableManager.updateSession(sessionData);
		cookie.setValue(sessionID + " " + Double.toString(versionID) + " "
				+ serverList);

		response.addCookie(cookie);
		response.setContentType("text/html");

		// error message to display if text crosses the size limit
		if (sizeOverLimit) {
			errorString = "error : please enter shorter text";
		}
		PrintWriter out = response.getWriter();
		String docType = "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0 "
				+ "Transitional//EN\">\n";
		out.println(docType
				+ "<HTML>\n"
				+ "<HEAD><TITLE>LSI Assignment 4: </TITLE></HEAD>\n"
				+ "<body style=\"background-color:#E8E8E8;\">"
				+

				"<big><b>"
				+ "("
				+ counter
				+ ")"
				+ value
				+ "</big></b>"
				+ "<form method=POST action=\"replace\">"
				+ "<input type=submit name=cmd value=Replace>"
				+ "<input type=text name=NewText size=40 maxlength=1024>"
				+ "<p style=\"font-family:times;color:red\">"
				+ errorString
				+ "</p>"
				+ " </form> "
				+ "<form method=POST action=\"refresh\"><input type=submit name=cmd value=Refresh></form>"
				+ "<form method=POST action=\"logout\">"
				+ "<input type=submit name=cmd value=LogOut>"
				+ "<br><br> IP Addr:Port - "
				+ InetAddress.getLocalHost().getHostAddress() + ":"
				+ AppUtil.getPort() + "</form></BODY></HTML>");

	}

}
